package comm.net.cli;

import comm.net.protocol.Protobuf;
import comm.net.protocol.Protocol;
import comm.utill.Errno;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;

public class Client {
    protected Bootstrap m_bootstrap;
    protected EventLoopGroup m_workerGroup;
    protected ChannelFuture m_future;

    // 给ClientHandler设置数据用的Protocol
    protected Protocol m_sendProtocol;
    protected Protocol m_recvProtocol;

    // 手动关闭线程组
    protected boolean m_manualClose = false;

    // 初始化并且设置手动关闭线程组
    public int init(boolean manualClose){
        m_manualClose = manualClose;
        return this.init();
    }

    public int init(){
        final Client client = this;

        m_workerGroup = new NioEventLoopGroup();
        m_bootstrap = new Bootstrap();
        m_bootstrap.group(m_workerGroup).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                // decoded
                socketChannel.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4));
                //这里是收到服务端发过来的消息,所以是对服务端的response解码
                socketChannel.pipeline().addLast(new ProtobufDecoder(Protobuf.Pro.getDefaultInstance()));
                // encoded
                socketChannel.pipeline().addLast(new LengthFieldPrepender(4));
                socketChannel.pipeline().addLast(new ProtobufEncoder());
                socketChannel.pipeline().addLast(new ClientHandler(client));
            }
        });

        return 0;
    }

    protected int send(Protocol sendProtocol) {
        m_sendProtocol = sendProtocol;

        try {
            m_future = m_bootstrap.connect("127.0.0.1", 8990).sync();
        } catch (Exception e) {
            return Errno.Svr.SEND_ERROR;
        }

        return Errno.OK;
    }

    protected int recv(Protocol recvProtocol) {

        try {
            // 应用程序会一直等待，直到channel关闭
            m_future.channel().closeFuture().sync();
            if (m_recvProtocol == null) {
                return Errno.ARGS_ERROR;
            }
            recvProtocol.setPro(m_recvProtocol.getPro());
        } catch (Exception e) {
            return Errno.Svr.RECV_ERROR;
        }

        return Errno.OK;
    }

    protected void close(){
        m_future.channel().close();
        // 默认是在调用close的时候一起关闭线程组，但是允许设置为手动关闭
        if(!m_manualClose){
            m_workerGroup.shutdownGracefully();
        }
    }

    // 关闭线程组
    protected void closeGroup() {
        m_workerGroup.shutdownGracefully();
    }


    // 只是在给ClientHandler调用的，方便设置数据
    protected Protocol getSendProtocol() {
        return m_sendProtocol;
    }

    protected void setRecvProtocol(Protocol recvProtocol) {
        m_recvProtocol = recvProtocol;
    }
}
